/**
 * @file
 * @author dousha 
 * @date 2020/6/13.
 */

#include "schedule.h"
#include "../interrupt/interrupt.h"
#include "../peripheral/clock.h"
#include "./task.h"

/**
 * 延迟一定毫秒数。（10 的 -3 次方秒）。
 *
 * 这个延时函数不一定是准确的，即该延迟不保证一定会在给定毫秒数后继续执行。
 *
 * @param time 延迟时长
 */
extern void delay_ms(uint32_t time) {
	delay_us(time * 1000u);
}

/**
 * 延迟一定微秒数。（10 的 -6 次方秒）。
 *
 * 这个延时函数不一定是准确的，即该延迟不保证一定会在给定微秒数后继续执行。
 *
 * @param time 延迟时长
 */
extern void delay_us(uint32_t time) {
	delay_tick(time / 100); // FIXME: Use indenpendent expression here!
}

/**
 * 延迟一定刻数。
 *
 * 如果你不知道刻数代表什么，请不要使用这个函数。
 *
 * 这个函数不保证延迟上界。
 *
 * @param tick 延迟刻数
 */
void delay_tick(uint32_t tick) {
	// FIXME: it doesn't work
	uint32_t nextDecade = clock_decade_after_ticks(tick);
	uint32_t nextTime = clock_time_after_ticks(tick);
	task_reschedule(nextDecade, nextTime);
	task_mark_timed_wait();
	yield();
}

/**
 * 阻塞一定毫秒数。
 * 
 * @param ms 毫秒数
 * 
 * @attention 这个函数会强制当前任务不调出以获得最佳精度，但是会造成严重的性能影响。
 */
void block_ms(uint32_t ms) {
	block_us(ms * 1000u);
}

/**
 * 阻塞一定微秒数。
 * 
 * @param us 微秒数
 * 
 * @attention 这个函数会强制当前任务不调出以获得最佳精度，但是会造成严重的性能影响。
 */
void block_us(uint32_t us) {
	block_tick(us / 10); // FIXME: make it time dependent
}

/**
 * 阻塞一定刻数。
 * 
 * 如果你不知道刻数代表什么，请不要使用这个函数。
 * 
 * @param tick 阻塞的刻数
 * 
 * @attention 这个函数会强制当前任务不调出以获得最佳精度，但是会造成严重的性能影响。
 */
void block_tick(uint32_t tick) {
	// TODO
}

/**
 * 进入第一个用户程序。
 * 
 * @invokedBy{task_init}
 */
void user_task_enter() {
	__asm volatile("mov r0, %0\r\nsvc %0" ::"i"(SVC_INIT));
}

/**
 * 释放时间片给下一个任务。
 */
void yield() {
	__asm volatile ("mov r0, %0\r\nsvc %0" :: "i" (SVC_YIELD));
}

/**
 * 结束此任务。
 */
void terminate(Result result) {
	__asm volatile("mov r0, %0\r\nsvc %0" ::"i"(SVC_EXIT));
}
